package cash.cmp.personal_financial_system.service.impl;

import cash.cmp.personal_financial_system.mapper.BillMapper;
import cash.cmp.personal_financial_system.model.Bill;
import cash.cmp.personal_financial_system.model.account.Graph;
import cash.cmp.personal_financial_system.model.account.MoneyOutIn;
import cash.cmp.personal_financial_system.model.account.Pie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;


@Service
//配置事务回滚
@Transactional(rollbackFor = Exception.class)
public class BillServiceImpl {

    @Autowired
    public BillMapper billMapper;

    final private String[] BigType = {"餐饮副食","日用百货","休闲娱乐", "金融", "个人", "其他类" };

    public List<Bill> findAllBill(){
        return billMapper.findAllBill();
    }

    public List<Bill> findBill(Integer id){
        return billMapper.findBill(id);
    }

    public List<Bill> findBillByAll(Integer id, Date startTime, Date endTime, String type,String bigType, int page, int pageSize){
        int finalPage = (page - 1 )* pageSize;
        return billMapper.findBillByAll(id,startTime,endTime, type,bigType,finalPage, pageSize);
    }

    public List<Bill> findBillByApp(Integer id, Integer relatedId,Date startTime, Date endTime, int page, int pageSize){
        int finalPage = (page - 1 )* pageSize;
        return billMapper.findBillByApp(id,relatedId,startTime,endTime, finalPage, pageSize);
    }
    public List<Bill> searchByApp(Integer id, Integer relatedId,Double money , String like, int page, int pageSize){
        int finalPage = (page - 1 )* pageSize;
        return billMapper.searchByApp(id,relatedId,money,like, finalPage, pageSize);
    }
    public int countSearchByApp(Integer id, Integer relatedId, Double money, String like){
        return billMapper.countSearchByApp(id,relatedId,money,like);
    }

    /* 饼状图实现底层代码 */
    public List<Map<String, Double>> BillByPie(Integer id, Integer relatedId, Date startTime, Date endTime){
        Calendar c = Calendar.getInstance();
        c.setTime(endTime);
        c.add(Calendar.DAY_OF_MONTH, 1);
        // endTime的后一天
        Date endTimeAdd = c.getTime();

        Pie[] piesIn = billMapper.BillByPie(id,relatedId,startTime,endTime,endTimeAdd,1);
        Pie[] piesOut = billMapper.BillByPie(id,relatedId,startTime,endTime,endTimeAdd,0);

        Map<String, Double> mapsIn = new HashMap<>();
        Map<String, Double> mapsOut = new HashMap<>();
        Map<String, Double> maps = new HashMap<>();
        for (Pie pie: piesIn) {
            mapsIn.put(pie.getBigType(),pie.getMoney());
        }
        for(int i = 0; i < 6; i++) {
            if( !mapsIn.containsKey(BigType[i])) {
                mapsIn.put(BigType[i],0.0);
            }
        }

        for (Pie pie: piesOut) {
            mapsOut.put(pie.getBigType(),pie.getMoney());
        }
        for(int i = 0; i < 6; i++) {
            if( !mapsOut.containsKey(BigType[i])) {
                mapsOut.put(BigType[i],0.0);
            }
        }
        for(int i = 0; i < 6; i++) {
            maps.put(BigType[i], (mapsIn.get(BigType[i]) - mapsOut.get(BigType[i]) ));
        }

        List<Map<String, Double>> list = new ArrayList<>();
        list.add(mapsIn);
        list.add(mapsOut);
        list.add(maps);
        return list;
    }

    // 柱状图和折线图数据支持
    public List<Graph[]> BillByGraph1(Integer id, Integer relatedId,Date startTime, Date endTime){
        List<Graph[]> list = new ArrayList<>();
        Calendar c = Calendar.getInstance();
        c.setTime(endTime);
        c.add(Calendar.DAY_OF_MONTH, 1);
        // endTime的后一天
        Date endTimeAdd = c.getTime();


        // 1. 求收入 billType = 0 的数据，及收入的数据
        Graph[] graphsIn = billMapper.BillByGraph1(id,relatedId,startTime,endTime,endTimeAdd,0);
        System.out.println("graphsIn : " + Arrays.toString(graphsIn));

        // 2. 求收入 billType = 1 的数据，及支出的数据
        Graph[] graphsOut = billMapper.BillByGraph1(id,relatedId,startTime,endTime,endTimeAdd,1);

        // 3. 求结余的数据
        Graph[] graphs = new Graph[7];

        for (int i = 0; i < 7; i++) {
            graphs[i] = new Graph(graphsIn[i].getDuration(),graphsIn[i].getSum() - graphsOut[i].getSum() );
        }

        list.add(graphsIn);
        list.add(graphsOut);
        list.add(graphs);

        return list;
    }

    public List<Graph[]> BillByGraph2(Integer id, Integer relatedId,Date startTime, Date endTime){
        List<Graph[]> list = new ArrayList<>();
        Calendar c = Calendar.getInstance();
        c.setTime(endTime);
        c.add(Calendar.DAY_OF_MONTH, 1);
        // endTime的后一天
        Date endTimeAdd = c.getTime();

        // 1. 求收入 billType = 0 的数据，及收入的数据
        Graph[] graphsIn = billMapper.BillByGraph2(id,relatedId,startTime,endTime,endTimeAdd,0);


        // 2. 求收入 billType = 1 的数据，及支出的数据
        Graph[] graphsOut = billMapper.BillByGraph2(id,relatedId,startTime,endTime,endTimeAdd,1);

        // 3. 求结余的数据
        int len = graphsIn.length;
        Graph[] graphs = new Graph[len];
        for (int i = 0; i < len; i++) {
            graphs[i] = new Graph(graphsIn[i].getDuration(), graphsIn[i].getSum() - graphsOut[i].getSum());
        }

        list.add(graphsIn);
        list.add(graphsOut);
        list.add(graphs);

        return list;
    }

    public List<Graph[]> BillByGraph3(Integer id, Integer relatedId,Date startTime, Date endTime){
        List<Graph[]> list = new ArrayList<>();
        Calendar c = Calendar.getInstance();
        c.setTime(endTime);
        c.add(Calendar.DAY_OF_MONTH, 1);
        // endTime的后一天
        Date endTimeAdd = c.getTime();

        // 1. 求收入 billType = 0 的数据，及收入的数据
        Graph[] graphsIn = billMapper.BillByGraph3(id,relatedId,startTime,endTime,endTimeAdd,0);


        // 2. 求收入 billType = 1 的数据，及支出的数据
        Graph[] graphsOut = billMapper.BillByGraph3(id,relatedId,startTime,endTime,endTimeAdd,1);

        // 3. 求结余的数据
        Graph[] graphs = new Graph[12];
        for (int i = 0; i < 12; i++) {
            graphs[i] = new Graph(graphsIn[i].getDuration(), graphsIn[i].getSum() - graphsOut[i].getSum());
        }
        list.add(graphsIn);
        list.add(graphsOut);
        list.add(graphs);

        return list;
    }

    public int countByAll(Integer id, Date startTime, Date endTime, String type ,String bigType){
        return billMapper.countByAll(id,startTime,endTime, type, bigType);
    }
    public int countByApp(Integer id, Integer relatedId, Date startTime, Date endTime){
        return billMapper.countByApp(id, relatedId,startTime,endTime);
    }

    public Map<Integer, Double> sumByApp(Date startTime, Date endTime, Integer id, Integer relatedId){
        MoneyOutIn[] moneys = billMapper.sumByApp(startTime,endTime, id, relatedId);

        Map<Integer, Double> maps = new HashMap<>();
        for (MoneyOutIn money: moneys) {
            maps.put(money.getBillType(), money.getSum());
        }
        if(!maps.containsKey(0)){
            maps.put(0, 0.0);
        }
        if(!maps.containsKey(1)){
            maps.put(1, 0.0);
        }
        return maps;
    }

    public List<Bill> findBillByPage(int page, int pageSize){
        int finalPage = (page - 1 )* pageSize;
        return billMapper.findBillByPage(finalPage, pageSize);
    }

    public List<Bill> findBillByPageId(int page, int pageSize, int id){
        int finalPage = (page - 1 )* pageSize;
        return billMapper.findBillByPageId(finalPage, pageSize, id);
    }


    public int billCount(){
        return billMapper.billCount();
    }

    public int billCountById(int id){
        return billMapper.billCountById(id);
    }

    public Boolean updateBill(Bill bill){
        return billMapper.updateBill(bill);
    }

    public Boolean insertBill(Bill bill){
        return billMapper.insertBill(bill);
    }

    public Boolean deleteBill(String billId){
        return billMapper.deleteBill(billId);
    }

    public Boolean deleteBillById(Integer id){
        return billMapper.deleteBillById(id);
    }

    public Boolean saveList(List<Bill> list){
        return billMapper.saveList(list);
    }

    public Boolean isBigType(String type) {
        return "餐饮副食".equals(type) || "日用百货".equals(type) || "休闲娱乐".equals(type) || "金融".equals(type) || "个人".equals(type) || "其他类".equals(type);
    }

}
